﻿/// <reference path="ModerationQueueStatus.js" />
/// <reference path="../utilities/FXDom.js" />
/// <reference path="../utilities/Xpcom.js" />
///--------------------------------------------------------------------
/// <file name="Post.js">
///   Provides information about a particular post on Neoseeker.
/// </file>
///--------------------------------------------------------------------

NAMFox.ns(function() { with (NAMFox) {

this.Post = function(postHeaderRow) {
    /// <summary>Initializes a new instance of the Post class.</summary>
    /// <param name="postHeaderRow" type="TableRowElement" domElement="true">
    ///   The first table row which indicates a new post. This table row
    ///   must have a numeric ID.
    /// </param>
    
    this.headerRow = postHeaderRow;
    this.contentRow = this.headerRow.nextSibling.nextSibling;
    this.linkRow = this.contentRow.nextSibling.nextSibling;
}

Post.linkExpr = /m=(\d+)/;
Post.inViewExpr = /<b style="color: red;"><u>Awaiting Moderation<\/u><\/b>/;
Post.moderatorExpr = /<b>Restore Message<\/b>/;
Post.reportedExpr = /<b style="color: red;"><u>.*?<\/u><\/b>/;

Post.prototype = {
    _getFollowingPostContent: function() {
        /// <summary>
        ///   Gets the content that appears after the user's post content but before the end of the table cell.
        ///   This includes information such as the signature and any text regarding the moderation queue.
        /// </summary>
        /// <returns type="String" />

        var postContent = $FX(this.contentRow).find("td").html();
        $.verbose("POST CONTENT: " + postContent);
        $.assert(postContent, "The post table cell should have content.");

        var index = postContent.indexOf('<div id="em_') + 1;
        var stackCount = 1;

        do {
            var nextOpenDiv = postContent.indexOf("<div", index);
            var nextCloseDiv = postContent.indexOf("</div>", index);

            if (nextOpenDiv > -1 && nextOpenDiv < nextCloseDiv) {
                ++stackCount;
                index = nextOpenDiv + 1;
            }
            else {
                --stackCount;
                // 6 === "</div>".length
                index = nextCloseDiv + 6;
            }
        }
        while (stackCount !== 0);

        return postContent.substr(index);
    },

    getAuthor: function() {
        /// <summary>Gets the user name of the person who authored this post.</summary>
        /// <returns type="String" />

        var authorName = $FX(this.headerRow).find("strong:first").html();
        $.assert(authorName, "The author name should exist.");

        return authorName;
    },

    getBackgroundColor: function() {
        /// <summary>Gets the background color of this post.</summary>

        var backgroundColor = this.headerRow.ownerDocument.defaultView.getComputedStyle(this.headerRow, null).backgroundColor;
        return Color.fromCss(backgroundColor).toHex();
    },

    getMarkup: function(callback) {
        /// <summary>Gets the markup for a particular post.</summary>
        /// <returns type="String" />

        // Not null and not undefined
        if (this._rawHtml != null) {
            MarkupTranslator.getMarkupFromHtml(this.contentRow.ownerDocument, this._rawHtml, callback);
            return;
        }

        $.fail("Should not reach this point.");

        var postContentCell = $FX(this.contentRow).find("td");
        var postHtmlContainer = postContentCell.find("div[id=em_" + this.getMessageId() + "]");

        if (postHtmlContainer.length === 0) {
            return postContentCell.find("textarea").val();
        }

        return $.getMarkupFromInnerHtml(postHtmlContainer.html());
    },

    getMessageId: function() {
        /// <summary>Gets the message ID of this post.</summary>
        /// <returns type="Number" integer="true" />

        var messageLink = $FX(this.headerRow).find("div[className*=small right] a").attr("href");
        $.assert(messageLink, "The message link should exist.");

        if (messageLink) {
            var linkMatches = messageLink.match(Post.linkExpr);
            $.assert(linkMatches, "The regular expression match for the message ID should always match.");

            if (linkMatches) {
                return linkMatches[1];
            }
        }

        return null;
    },

    getPostRegExp: function() {
        /// <summary>Gets the regular expression that can match only this post.</summary>
        /// <returns type="RegExp" />

        return new RegExp('<!-- msg ' + this.getMessageId() + ' -->([\\s\\S]*?)<!-- endmsg ' + this.getMessageId() + ' -->');
    },

    getReplyNumber: function () {
        /// <summary>Returns the number of what the post is in the thread</summary>
        /// <returns type="Number" />

        return this.headerRow.id;
    },

    getModerationQueueStatus: function() {
        /// <summary>Gets whether this post is awaiting moderation but has not been removed from public view.</summary>
        /// <returns type="ModerationQueueStatus" />

        var followingPostContent = this._getFollowingPostContent();

        var reported = followingPostContent.match(Post.reportedExpr) ? ReportedStatus.Reported : ReportedStatus.NotReported;
        var view = ViewStatus.InView;
        var moderator = ModeratorStatus.Member;

        if (reported === ReportedStatus.Reported) {
            view = followingPostContent.match(Post.inViewExpr) ? ViewStatus.InView : ViewStatus.OutOfView;
            moderator = followingPostContent.match(Post.moderatorExpr) ? ModeratorStatus.Moderator : ModeratorStatus.Member;
        }

        return new ModerationQueueStatus(reported, view, moderator);
    },

    getSubject: function() {
        /// <summary>Gets the subject of this post.</summary>
        /// <returns type="String" />

        var subject = $FX(this.headerRow).find("strong:last").html();
        $.assert(subject, "The post should have a subject.");

        return subject.replace(/\&lt;/gi, "<").replace(/\&gt;/gi, ">").replace(/\&amp;/gi, "&");
    },

    isSignatureDisplayed: function() {
        /// <summary>Determines whether the post has a signature displayed.</summary>
        /// <returns type="Boolean" />

        return $.contains(this._getFollowingPostContent(), "-------------------");
    },

    setHtml: function(responseText) {
        var results = responseText.match(this.getPostRegExp());

        $.assert(results, 'Could not find the post in the responseText.');

        if (results) {
            results = results[1];
            results = results.replace(/<p> \[ Check <a href="\/forums\/index.php\?fn=moderation_queue&amp;f=\d+">moderation queue<\/a> to see who reported this post \](\s*| <\/div>[\s\S]+)$/, "");
            results = results.replace(/<p> \[ This message has been moved to the <a href="\/forums\/index.php\?fn=moderation_queue&amp;f=\d+">moderation queue<\/a> and is being shown to you due to your moderator status \](\s*| <\/div>[\s\S]+)$/, "");

            this._rawHtml = results;
        }
    },

    setSubject: function(subject) {
        /// <summary>Sets the subject of this post only on the Neoseeker page (not in Neoseeker's data).</summary>

        $FX(this.headerRow).find("strong:last").html(subject);
    }
};

}});